package com.example.smartpark.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.smartpark.dto.ParkingLotAddDTO;
import com.example.smartpark.dto.ParkingLotUpdateDTO;
import com.example.smartpark.exception.BusinessException;
import com.example.smartpark.mapper.ParkingLotMapper;
import com.example.smartpark.mapper.ParkingSpaceMapper;
import com.example.smartpark.model.ParkingLot;
import com.example.smartpark.service.ParkingLotService;
import com.example.smartpark.vo.ParkingLotVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.stream.Collectors;

/**
 * 停车场服务实现类
 */
@Slf4j
@Service
public class ParkingLotServiceImpl extends ServiceImpl<ParkingLotMapper, ParkingLot> implements ParkingLotService {

    @Autowired
    private ParkingSpaceMapper parkingSpaceMapper;

    /**
     * 分页获取停车场列表
     *
     * @param page 页码
     * @param size 每页数量
     * @param name 停车场名称（可选）
     * @param status 状态（可选）
     * @return 分页停车场列表
     */
    @Override
    public IPage<ParkingLotVO> getParkingLotPage(int page, int size, String name, Integer status) {
        log.info("分页获取停车场列表: page={}, size={}, name={}, status={}", page, size, name, status);
        
        // 构建查询条件
        LambdaQueryWrapper<ParkingLot> queryWrapper = new LambdaQueryWrapper<>();
        
        // 根据停车场名称模糊查询
        if (StringUtils.hasText(name)) {
            queryWrapper.like(ParkingLot::getName, name);
        }
        
        // 根据状态筛选
        if (status != null) {
            queryWrapper.eq(ParkingLot::getStatus, status);
        }
        
        // 按创建时间降序排序
        queryWrapper.orderByDesc(ParkingLot::getCreatedAt);
        
        // 分页查询
        Page<ParkingLot> pageParam = new Page<>(page, size);
        IPage<ParkingLot> parkingLotPage = page(pageParam, queryWrapper);
        
        // 转换为VO对象
        return parkingLotPage.convert(this::convertToVO);
    }

    /**
     * 获取停车场详情
     *
     * @param id 停车场ID
     * @return 停车场详情
     */
    @Override
    public ParkingLotVO getParkingLotById(Integer id) {
        log.info("获取停车场详情: id={}", id);
        
        ParkingLot parkingLot = getById(id);
        if (parkingLot == null) {
            throw new BusinessException("停车场不存在");
        }
        
        return convertToVO(parkingLot);
    }

    /**
     * 添加停车场
     *
     * @param parkingLotAddDTO 添加停车场DTO
     * @return 添加的停车场信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ParkingLotVO addParkingLot(ParkingLotAddDTO parkingLotAddDTO) {
        log.info("添加停车场: parkingLotAddDTO={}", parkingLotAddDTO);
        
        // 检查停车场名称是否已存在
        if (checkNameExists(parkingLotAddDTO.getName(), null)) {
            throw new BusinessException("停车场名称已存在");
        }
        
        // 检查可用车位数是否小于等于总车位数
        if (parkingLotAddDTO.getAvailableSpaces() > parkingLotAddDTO.getTotalSpaces()) {
            throw new BusinessException("可用车位数不能大于总车位数");
        }
        
        // 创建停车场对象
        ParkingLot parkingLot = new ParkingLot();
        BeanUtils.copyProperties(parkingLotAddDTO, parkingLot);
        
        // 保存停车场信息
        boolean success = save(parkingLot);
        if (!success) {
            throw new BusinessException("添加停车场失败");
        }
        
        return convertToVO(parkingLot);
    }

    /**
     * 更新停车场信息
     *
     * @param id 停车场ID
     * @param parkingLotUpdateDTO 更新停车场DTO
     * @return 更新后的停车场信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ParkingLotVO updateParkingLot(Integer id, ParkingLotUpdateDTO parkingLotUpdateDTO) {
        log.info("更新停车场: id={}, parkingLotUpdateDTO={}", id, parkingLotUpdateDTO);
        
        // 获取停车场信息
        ParkingLot parkingLot = getById(id);
        if (parkingLot == null) {
            throw new BusinessException("停车场不存在");
        }
        
        // 检查停车场名称是否已存在
        if (parkingLotUpdateDTO.getName() != null && 
            !parkingLotUpdateDTO.getName().equals(parkingLot.getName()) && 
            checkNameExists(parkingLotUpdateDTO.getName(), id)) {
            throw new BusinessException("停车场名称已存在");
        }
        
        // 检查可用车位数是否小于等于总车位数
        if (parkingLotUpdateDTO.getTotalSpaces() != null && parkingLotUpdateDTO.getAvailableSpaces() != null) {
            if (parkingLotUpdateDTO.getAvailableSpaces() > parkingLotUpdateDTO.getTotalSpaces()) {
                throw new BusinessException("可用车位数不能大于总车位数");
            }
        } else if (parkingLotUpdateDTO.getTotalSpaces() != null) {
            if (parkingLot.getAvailableSpaces() > parkingLotUpdateDTO.getTotalSpaces()) {
                throw new BusinessException("可用车位数不能大于总车位数");
            }
        } else if (parkingLotUpdateDTO.getAvailableSpaces() != null) {
            if (parkingLotUpdateDTO.getAvailableSpaces() > parkingLot.getTotalSpaces()) {
                throw new BusinessException("可用车位数不能大于总车位数");
            }
        }
        
        // 更新停车场信息
        boolean needsUpdate = false;
        
        if (parkingLotUpdateDTO.getName() != null && !parkingLotUpdateDTO.getName().equals(parkingLot.getName())) {
            parkingLot.setName(parkingLotUpdateDTO.getName());
            needsUpdate = true;
        }
        
        if (parkingLotUpdateDTO.getAddress() != null && !parkingLotUpdateDTO.getAddress().equals(parkingLot.getAddress())) {
            parkingLot.setAddress(parkingLotUpdateDTO.getAddress());
            needsUpdate = true;
        }
        
        if (parkingLotUpdateDTO.getTotalSpaces() != null && !parkingLotUpdateDTO.getTotalSpaces().equals(parkingLot.getTotalSpaces())) {
            parkingLot.setTotalSpaces(parkingLotUpdateDTO.getTotalSpaces());
            needsUpdate = true;
        }
        
        if (parkingLotUpdateDTO.getAvailableSpaces() != null && !parkingLotUpdateDTO.getAvailableSpaces().equals(parkingLot.getAvailableSpaces())) {
            parkingLot.setAvailableSpaces(parkingLotUpdateDTO.getAvailableSpaces());
            needsUpdate = true;
        }
        
        if (parkingLotUpdateDTO.getOpenTime() != null && !parkingLotUpdateDTO.getOpenTime().equals(parkingLot.getOpenTime())) {
            parkingLot.setOpenTime(parkingLotUpdateDTO.getOpenTime());
            needsUpdate = true;
        }
        
        if (parkingLotUpdateDTO.getCloseTime() != null && !parkingLotUpdateDTO.getCloseTime().equals(parkingLot.getCloseTime())) {
            parkingLot.setCloseTime(parkingLotUpdateDTO.getCloseTime());
            needsUpdate = true;
        }
        
        if (parkingLotUpdateDTO.getContactPhone() != null && !parkingLotUpdateDTO.getContactPhone().equals(parkingLot.getContactPhone())) {
            parkingLot.setContactPhone(parkingLotUpdateDTO.getContactPhone());
            needsUpdate = true;
        }
        
        if (parkingLotUpdateDTO.getStatus() != null && !parkingLotUpdateDTO.getStatus().equals(parkingLot.getStatus())) {
            parkingLot.setStatus(parkingLotUpdateDTO.getStatus());
            needsUpdate = true;
        }
        
        // 更新停车场信息
        if (needsUpdate) {
            boolean success = updateById(parkingLot);
            if (!success) {
                throw new BusinessException("更新停车场信息失败");
            }
        }
        
        return convertToVO(parkingLot);
    }

    /**
     * 删除停车场
     *
     * @param id 停车场ID
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteParkingLot(Integer id) {
        log.info("删除停车场: id={}", id);
        
        // 获取停车场信息
        ParkingLot parkingLot = getById(id);
        if (parkingLot == null) {
            throw new BusinessException("停车场不存在");
        }
        
        // TODO: 检查停车场是否有相关的车位、停车记录、预约记录等数据
        
        // 删除停车场
        return removeById(id);
    }

    /**
     * 检查停车场名称是否已存在
     *
     * @param name 停车场名称
     * @param excludeId 排除的停车场ID（用于更新时）
     * @return 是否存在
     */
    @Override
    public boolean checkNameExists(String name, Integer excludeId) {
        log.info("检查停车场名称是否已存在: name={}, excludeId={}", name, excludeId);
        
        // 构建查询条件
        LambdaQueryWrapper<ParkingLot> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ParkingLot::getName, name);
        
        // 排除当前停车场
        if (excludeId != null) {
            queryWrapper.ne(ParkingLot::getId, excludeId);
        }
        
        return count(queryWrapper) > 0;
    }

    /**
     * 更新停车场可用车位数
     *
     * @param id 停车场ID
     * @return 是否更新成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAvailableSpaces(Integer id) {
        log.info("更新停车场可用车位数: id={}", id);
        
        // 获取停车场信息
        ParkingLot parkingLot = getById(id);
        if (parkingLot == null) {
            throw new BusinessException("停车场不存在");
        }
        
        // 计算可用车位数
        int availableSpaces = parkingSpaceMapper.countAvailableSpaces(id);
        
        // 更新停车场可用车位数
        parkingLot.setAvailableSpaces(availableSpaces);
        
        return updateById(parkingLot);
    }

    /**
     * 将ParkingLot对象转换为ParkingLotVO对象
     *
     * @param parkingLot ParkingLot对象
     * @return ParkingLotVO对象
     */
    private ParkingLotVO convertToVO(ParkingLot parkingLot) {
        if (parkingLot == null) {
            return null;
        }
        
        ParkingLotVO parkingLotVO = new ParkingLotVO();
        BeanUtils.copyProperties(parkingLot, parkingLotVO);
        
        return parkingLotVO;
    }
} 